/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package bbchess.units.pieces;

import bbchess.units.ChessPiece;
import bbchess.units.ChessBoard;
import bbchess.units.ChessSquare;
import bbchess.util.ImageLoader;
import java.util.ArrayList;

/**
 *
 * @author Tyler
 */
public class King extends ChessPiece {

    private String kingCanCastle;

    public King(String color, ChessSquare position) {
        initPiece(color, position);
        kingCanCastle = "";
        setUnit("K");

        if (color.equals("black")) {
            setSprite(ImageLoader.getbKingImage());
        } else {
            setSprite(ImageLoader.getwKingImage());
        }

    }

    /**
     * Determines if the King can kingCanCastle.  This method should be called
     * after threatened squares have been updated. Preferrably after each 
     * time setMove() is called.
     * 
     * @return "long" if King can capture via Queenside kingCanCastle.
     * "short" if King can casle via Kingside kingCanCastle.
     * Null if the King can't kingCanCastle on this move.
     */
    public String canCastle() {

        /*
         * -King and Rook may not have moved from their starting squares.
         * -All of the spaces between the Rook and the King must be unoccupied.
         * -The King cannot be in Check.
         * -The squares that the King passes over cannot be under attack.
         */

        String castle = "";

        Rook kingSideRook = null;
        Rook queenSideRook = null;

        // If we're in check, we can't kingCanCastle, return null
        // TODO Needs work, calculates on next move.
        if (getPosition().getThreatened()) {
            return castle;
        }

        // If we're a white piece
        if (getColor().equals("white")) {
            board.updateBlackThreatenedMoves();
            kingSideRook = board.getWhiteKingSideRook();
            queenSideRook = board.getWhiteQueenSideRook();
        }

        // If we're a black piece
        else {
            board.updateWhiteThreatenedMoves();
            kingSideRook = board.getBlackKingSideRook();
            queenSideRook = board.getBlackQueenSideRook();
        }

        // Try for short kingCanCastle
        // King and Rook may not have moved from their starting squares (first move)
        if (kingSideRook != null && !kingSideRook.isCaptured()) {
            if (getMove() == 1 && kingSideRook.getMove() == 1) {

                // Assume we can kingCanCastle, if we can't, we will set to false
                boolean canCastle = true;

                ArrayList<ChessSquare> squaresToCheck = new ArrayList<ChessSquare>();

                // -All of the spaces between the Rook and the King must be unoccupied.
                // -The squares that the King passes over cannot be under attack.
                if (getColor().equals("white")) {
                    // check f1, g1
                    squaresToCheck.add(board.getChessSquares().get("f1"));
                    squaresToCheck.add(board.getChessSquares().get("g1"));
                }

                else {
                    // check f8, g8
                    squaresToCheck.add(board.getChessSquares().get("f8"));
                    squaresToCheck.add(board.getChessSquares().get("g8"));
                }

                // Check if squares are threatened or occupied.
                // Threatened squares need to have been refreshed for this to work!
                for (ChessSquare square : squaresToCheck) {
                    if ((square.getThreatened()) || (square.getContents() != null)) {
                        canCastle = false;
                    }
                }

                squaresToCheck.clear();

                if (canCastle) {
                    castle += "short";

                    if (getColor().equals("white")) {
                        addLegalMove("g1");
                    }
                    else {
                        addLegalMove("g8");
                    }
                }
            }
        }

        // Try for long kingCanCastle
        // King and Rook may not have moved from their starting squares
        if (queenSideRook != null && !queenSideRook.isCaptured()) {
            if (getMove() == 1 && queenSideRook.getMove() == 1) {

                // Assume we can kingCanCastle, if we can't, we will set to false
                boolean canCastle = true;

                ArrayList<ChessSquare> squaresToCheck = new ArrayList<ChessSquare>();

                // -All of the spaces between the Rook and the King must be unoccupied.
                // -The squares that the King passes over cannot be under attack.
                if (getColor().equals("white")) {
                    // check b1, c1, d1
                    squaresToCheck.add(board.getChessSquares().get("b1"));
                    squaresToCheck.add(board.getChessSquares().get("c1"));
                    squaresToCheck.add(board.getChessSquares().get("d1"));
                }

                else {
                    // check b8, c8, d8
                    squaresToCheck.add(board.getChessSquares().get("b8"));
                    squaresToCheck.add(board.getChessSquares().get("c8"));
                    squaresToCheck.add(board.getChessSquares().get("d8"));
                }

                // Check if squares are threatened or occupied.
                // Threatened squares need to have been refreshed for this to work!
                for (ChessSquare square : squaresToCheck) {
                    if ((square.getThreatened()) || (square.getContents() != null)) {
                        canCastle = false;
                    }
                }

                squaresToCheck.clear();

                if (canCastle) {
                    castle += "long";

                    if (getColor().equals("white")) {
                        addLegalMove("c1");
                    }
                    else {
                        addLegalMove("c8");
                    }
                }
            }
        }
        
        // Return the result
        // "" if not able to kingCanCastle
        // "short" if short
        // "long" if long
        // "shortlong" if both
        return castle;
    }

    @Override
    public void calculateLegalMoves() {
        if(board == null) {
            board = (ChessBoard) this.getParent();
        }
        
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, 1, 1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, 1, -1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, -1, 1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, -1, -1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, 0, 1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, 0, -1, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, 1, 0, false));
        addLegalMoves(board.calculatePath(getPosition().getPosition(), 1, -1, 0, false));

        // only update kingCanCastle if canCastle() is not empty.  it gets
        // cleared in the ChessBoard::setMove() method.
        String tempCastleString = canCastle();
        if (!tempCastleString.equals("")) {
            setKingCanCastle(tempCastleString);
        }
    }

    @Override
    public void updateMoves() {
        
        if (getColor().equals("white")) {
            board.updateBlackThreatenedMoves();
        }

        else {
            board.updateWhiteThreatenedMoves();
        }

        super.updateMoves();
        board.clearThreatenedSquares();
    }

    @Override
    public void adjustMoves() {
        // do nothing.  All of king's move logic is in it's addLegalMoves() method
    }

    @Override
    // special addlegalmoves for king, since king can only move to squares that aren't
    // threatened
    public void addLegalMoves(ArrayList<String> moves) {

        String move;

        if (!moves.isEmpty()) {
            move = moves.get(0);

            if (board.getChessSquares().get(move).getThreatened()) {
                //
            } else { // go ahead and add it. The square is safe!
                super.addLegalMoves(moves);
            }
        }
    }

    @Override
    public String addCapturableMove(String capturableMove) {

        if (capturableMove != null) {
            if (board.getChessSquares().get(capturableMove).getThreatened()) {
                // dont add it
                return "";
            } else { // go ahead and add it. The square is safe!
                super.addCapturableMove(capturableMove);
            }
        }
        return "";
    }

    @Override
    public void calculateCaptureMoves() {
        if(board == null) {
            board = (ChessBoard) this.getParent();
        }
        
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, 1, 1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, 1, -1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, -1, 1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, -1, -1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, 0, 1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, 0, -1));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, 1, 0));
        addCapturableMove(board.calculateCapture(getPosition().getPosition(), getColor(), 1, -1, 0));
    }

    @Override
    public void calculateThreatenedMoves() {
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, 1, 1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, 1, -1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, -1, 1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, -1, -1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, 0, 1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, 0, -1, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, 1, 0, true));
        addThreatenedMoves(board.calculatePath(getPosition().getPosition(), 1, -1, 0, true));
    }

    /**
     * @return the kingCanCastle
     */
    public String getKingCanCastle() {
        return kingCanCastle;
    }

    /**
     * @param kingCanCastle the kingCanCastle to set
     */
    public void setKingCanCastle(String kingCanCastle) {
        this.kingCanCastle = kingCanCastle;
    }
}